/**
 * 跨操作系统统一接口 for 单片机裸机实现
 */

#include <stdlib.h>
#include <time.h>

// !!! 注意: 这里 unios_baremetal 依赖了 MCU 相关接口 !!!
#include "mcu.h"
#include "cccompat.h"
#include "unios.h"

// ======================================================================================
// 基础功能
// ======================================================================================

void* unios_malloc(size_t size) {
	return malloc(size);
}

void unios_free(void *ptr) {
	if(ptr) free(ptr);
}

// exit() 既是 ANSI-C 函数也是 POSIX 函数
void exit(int code) {
    mcu_reboot(code);
}

// system() 既是 ANSI-C 函数也是 POSIX 函数
int system(const char *cmd) {
    // do nothing
    return -1;
}

time_t time(time_t *tm) {
    uint32_t rtcsec = mcu_clock_get_rtcsec();
    if(tm) *tm = rtcsec;
    return rtcsec;
}


// ======================================================================================
// 关于 CPU
// ======================================================================================

size_t unios_get_cpu_core_count() {
	return 1;
}


// ======================================================================================
// 关于时钟
// ======================================================================================

unios_us_t unios_us_now() {
    return mcu_clock_us_now();
}

unios_ms_t unios_ms_now() {
    return mcu_clock_ms_now();
}

void unios_us_delay(unios_us_t us) {
	mcu_clock_us_delay(us);
}

void unios_ms_delay(unios_ms_t ms) {
	mcu_clock_ms_delay(ms);
}

void unios_watchdog_feed() {
	mcu_watchdog_feed();
}

unios_sec_t unios_rtcsec_get() {
	return mcu_clock_get_rtcsec();
}

std_err_t unios_rtcsec_set(unios_sec_t sec) {
	return mcu_clock_set_rtcsec(sec);
}

std_err_t unios_rtc_set(int year, int month, int day, int hour, int minute, int second) {
	return mcu_clock_rtc_set(year, month, day, hour, minute, second);
}

std_err_t unios_rtc_get(int *year, int *month, int *day, int *hour, int *minute, int *second, int *weekday) {	
	return mcu_clock_rtc_get(year, month, day, hour, minute, second, weekday);
}

std_err_t unios_rtc_timezone_set(const char *tz) {
	return STD_ERR_NOT_SUPPORTED;
}

char* unios_rtc_local_string() {
	static char str[64];
	int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0, weekday = 0;
	unios_rtc_get(&year, &month, &day, &hour, &minute, &second, &weekday);
	snprintf(str, sizeof(str), "%4d-%2d-%2d(%1d) %2d:%2d:%2d", year, month, day, weekday, hour, minute, second);
	return str;
}

// ======================================================================================
// 关于临界区
// ======================================================================================

static mcu_istate_t _istate;

std_err_t unios_critical_section_init(unios_critical_section_t* pcs) {
	return STD_ERR_OK;
}

std_err_t unios_critical_section_enter(unios_critical_section_t cs, long wait_timeout_ms) {
	_istate = mcu_get_interrupts_state();
	mcu_disable_interrupts();
	return STD_ERR_OK;
}

void unios_critical_section_leave(unios_critical_section_t cs) {
	mcu_set_interrupts_state(_istate);
}

void unios_critical_section_destroy(unios_critical_section_t *cs/*in,out*/) {
}


// ======================================================================================
// 关于锁
// ======================================================================================

std_err_t unios_lock_init(unios_lock_t* plock, size_t count) {
	return STD_ERR_NOT_SUPPORTED;
}

std_err_t unios_lock(unios_lock_t lock, long wait_timeout_ms) {
	return STD_ERR_NOT_SUPPORTED;
}

std_err_t unios_unlock(unios_lock_t lock) {
	return STD_ERR_NOT_SUPPORTED;
}

void unios_lock_destroy(unios_lock_t *lock) {
}


// ======================================================================================
// 关于事件
// ======================================================================================
std_err_t unios_event_init(unios_event_t* pevent, bool manual_reset, bool init_state) {
	return STD_ERR_NOT_SUPPORTED;
}

std_err_t unios_event_set(unios_event_t event, bool signal) {
	return STD_ERR_NOT_SUPPORTED;
}

std_err_t unios_event_wait(unios_event_t event, long wait_timeout_ms) {
	return STD_ERR_NOT_SUPPORTED;
}

void unios_event_destroy(unios_event_t *pevent /*in,out*/) {
}


// ======================================================================================
// 关于线程
// ======================================================================================

std_err_t unios_thread_create(unios_thread_func_t func, void *cookie, unios_thread_priority_t priority, size_t stack_size, uint64_t cpu_affinity, unios_thread_t* pt) {
	return STD_ERR_NOT_SUPPORTED;
}

unios_thread_t unios_thread_this() {
	return (unios_thread_t)-1;
}


// ======================================================================================
// 关于文件
// ======================================================================================

CCC_WEAK unios_file_t unios_file_null() {
    return 0;
}

CCC_WEAK bool unios_file_is_valid(unios_file_t uf) {
    return uf != 0;
}

CCC_WEAK int64_t unios_file_size(const char *path) {
    return 0;
}

CCC_WEAK std_err_t unios_file_rename(const char *from, const char *to) {
    return STD_ERR_NOT_SUPPORTED;
}

CCC_WEAK std_err_t unios_file_delete(const char *path) {
    return STD_ERR_NOT_SUPPORTED;
}

CCC_WEAK unios_file_t unios_file_from_stdio_stream(FILE *fp) {
    return unios_file_null();
}

CCC_WEAK std_err_t unios_file_open(const char *path, unios_file_oflag_t oflag, unios_file_t *uf) {
    return STD_ERR_NOT_SUPPORTED;
}

CCC_WEAK void unios_file_destroy(unios_file_t *uf) {
    if(!uf || !unios_file_is_valid(*uf)) return;
    *uf = unios_file_null();
}

CCC_WEAK int64_t unios_file_datasize(unios_file_t uf) {
    return 0;
}

CCC_WEAK std_err_t unios_file_sync(unios_file_t uf) {
    return STD_ERR_NOT_SUPPORTED;
}

CCC_WEAK std_err_t unios_file_read(unios_file_t uf, void *buf, size_t nbyte, int64_t offset, size_t *rbyte) {
    return STD_ERR_NOT_SUPPORTED;
}

CCC_WEAK std_err_t unios_file_write(unios_file_t uf, const void *buf, size_t nbyte, int64_t offset, size_t *wbyte) {
    return STD_ERR_NOT_SUPPORTED;
}

CCC_WEAK void* unios_file_mmap(unios_file_t uf, uint64_t offset, uint64_t size, uint64_t flags1, uint64_t flags2, void **mmptr/*out*/, uint64_t *mmsize/*out*/) {
	// 不支持
    return NULL;
}

CCC_WEAK void unios_file_munmap(void *mmptr, uint64_t mmsize) {
	// 不支持
}

CCC_WEAK int unios_file_ioctl(unios_file_t uf, int cmd, void *opt, size_t opt_size) {
	// 不支持
    return -1;
}
